#include <bitset>
#include <cmath>
#include "agentModAddRule.h"

using namespace std;

void agentModAddRule::run()
{
    solution* parent = thePool->getRandomSolution();

    solution* child = new solution(parent);

    // Get Random Node
    node* tmp = child->getRoot();
    assert(tmp != NULL);
    vector<pair<node *,char> > candidateNodes;
    candidateNodes.push_back(make_pair(tmp,'-'));
    while(tmp != NULL)
    {
        if (rand() % 2 == 0)
        {
            tmp = tmp->getLeft();
            candidateNodes.push_back(make_pair(tmp,'l'));
        }
        else
        {
            tmp = tmp->getRight();
            candidateNodes.push_back(make_pair(tmp,'r'));
        }
    }

    int ndx = (rand() % (candidateNodes.size() - 1)) + 1;

    assert(ndx >= 1 && ndx < candidateNodes.size());

    if (candidateNodes[ndx].first != NULL) delete candidateNodes[ndx].first;

    // Find records to train on
    bitset<TRAIN_RECORD_COUNT> records;
    records.set();

    for (int j = 0; j < TRAIN_RECORD_COUNT; j++)
    {
        record* tmpRecord = thePool->getTrainingSet()->getNthRecord(j);
        for(int i = 0; i < ndx && records[i]; i++)
        {
            bool left = candidateNodes[i].first->evaluatesLeft(tmpRecord);
            if ((left && candidateNodes[i+1].second != 'l') ||
                (!left && candidateNodes[i+1].second != 'r'))
               records.reset(i);
        }
    }


    if (candidateNodes[ndx].second == 'l')
        candidateNodes[ndx-1].first->setLeft(determineSplit(&records));
    else
        candidateNodes[ndx-1].first->setRight(determineSplit(&records));

    insert(child, parent);
}
